// 版权归GoFrame作者(https://goframe.org)所有。保留所有权利。
//
// 本源代码形式受MIT许可证条款约束。
// 如果未随本文件一同分发MIT许可证副本，
// 您可以在https://github.com/gogf/gf处获取。
// md5:a9832f33b234e3f3

// Package gcharset 实现字符集转换功能。
//
// 支持的字符集：
//
// 中文：GBK/GB18030/GB2312/Big5
//
// 日本语：EUCJP/ISO2022JP/ShiftJIS
//
// 韩语：EUCKR
//
// Unicode：UTF-8/UTF-16/UTF-16BE/UTF-16LE
//
// 其他：macintosh/IBM*/Windows*/ISO-*（*表示各种变种）
// md5:5f95b30c9186a77b
package 字符集类

import (
	"bytes"
	"context"
	"io"

	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/ianaindex"
	"golang.org/x/text/transform"

	gcode "gitee.com/go_888/goframe/errors/gcode"
	gerror "gitee.com/go_888/goframe/errors/gerror"
	"gitee.com/go_888/goframe/internal/intlog"
)

var (
	// Alias for charsets.
	charsetAlias = map[string]string{
		"HZGB2312": "HZ-GB-2312",
		"hzgb2312": "HZ-GB-2312",
		"GB2312":   "HZ-GB-2312",
		"gb2312":   "HZ-GB-2312",
	}
)

// X是否支持 返回字符集 `charset` 是否受支持。 md5:ecb209536b99e114
func X是否支持(字符集名称 string) bool {
	return getEncoding(字符集名称) != nil
}

// X转换 将 `src` 字符串的编码从 `srcCharset` 转换为 `dstCharset`，并返回转换后的字符串。
// 如果转换失败，则返回原 `src` 作为 `dst`。
// md5:d579c6167a34081f
func X转换(新字符集 string, 原字符集 string, 待转换文本 string) (返回值 string, 错误 error) {
	if 新字符集 == 原字符集 {
		return 待转换文本, nil
	}
	返回值 = 待转换文本
	// 将 `src` 转换为 UTF-8 编码。 md5:345cd013199770a3
	if 原字符集 != "UTF-8" {
		if e := getEncoding(原字符集); e != nil {
			tmp, err := io.ReadAll(
				transform.NewReader(bytes.NewReader([]byte(待转换文本)), e.NewDecoder()),
			)
			if err != nil {
				return "", gerror.X多层错误并格式化(err, `将字符串"%s"转换为UTF-8失败`, 原字符集)
			}
			待转换文本 = string(tmp)
		} else {
			return 返回值, gerror.X创建错误码并格式化(gcode.X变量_CodeInvalidParameter, `不支持的源字符集"%s"`, 原字符集)
		}
	}
	// 将UTF-8转换为`dstCharset`。 md5:4caf3880c33fb49d
	if 新字符集 != "UTF-8" {
		if e := getEncoding(新字符集); e != nil {
			tmp, err := io.ReadAll(
				transform.NewReader(bytes.NewReader([]byte(待转换文本)), e.NewEncoder()),
			)
			if err != nil {
				return "", gerror.X多层错误并格式化(err, `将字符串从UTF-8转换为"%s"失败`, 新字符集)
			}
			返回值 = string(tmp)
		} else {
			return 返回值, gerror.X创建错误码并格式化(gcode.X变量_CodeInvalidParameter, `不支持的目标字符集"%s"`, 新字符集)
		}
	} else {
		返回值 = 待转换文本
	}
	return 返回值, nil
}

// X转换到UTF8 将 `src` 字符串的字符集编码从 `srcCharset` 转换为 UTF-8，
// 并返回转换后的字符串。
// md5:ed113e096f11dcee
func X转换到UTF8(原字符集 string, 待转换文本 string) (返回值 string, 错误 error) {
	return X转换("UTF-8", 原字符集, 待转换文本)
}

// UTF8转换字符集 将 `src` 字符集编码从 UTF-8 转换为 `dstCharset`，
// 并返回转换后的字符串。
// md5:6d376918eb2969a6
func UTF8转换字符集(新字符集 string, UTF8文本 string) (返回值 string, 错误 error) {
	return X转换(新字符集, "UTF-8", UTF8文本)
}

// getEncoding 返回与 `charset` 对应的 encoding.Encoding 接口对象。如果 `charset` 不被支持，它将返回 nil。
// md5:8770abf28a404b1b
func getEncoding(charset string) encoding.Encoding {
	if c, ok := charsetAlias[charset]; ok {
		charset = c
	}
	enc, err := ianaindex.MIB.Encoding(charset)
	if err != nil {
		intlog.Errorf(context.TODO(), `%+v`, err)
	}
	return enc
}
